﻿namespace CommonData.Data.Core.SQLCore
{
    using CommonData.Data.Core;
    using CommonData.Entity;
    using CommonData.Model.Core;
    using System;
    using System.Collections.Generic;
    using System.Data;

    public class SqlHelper : IDbHelper, IDisposable
    {
        private IBaseHelper baseHelper;
        private IDbFactory factory;

        public int Add(IEntity entity)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateInsertSql(entity, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Add<T>(T t) where T: IEntity
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateInsertSql<T>(t, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Add(Type type, object value)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateInsertSql(type, value, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete<T>(T t) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(typeof(T), t, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete(IEntity entity)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(entity, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete<T>(T t, string[] propertyNames) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(typeof(T), t, out param, propertyNames);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete(IEntity entity, string propertyName)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(entity, out param, propertyName);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete(IEntity entity, string[] propertyNames)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(entity, out param, propertyNames);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete(Type type, object value)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(type, value, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete<T>(T t, string propertyName) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(typeof(T), t, out param, propertyName);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete(Type type, object value, string propertyName)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(type, value, out param, propertyName);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Delete(Type type, object value, string[] propertyNames)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateDeleteSql(type, value, out param, propertyNames);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }

        public int GetCount<T>() where T: class
        {
            string sqlString = this.Factory.CreateConverageSql(typeof(T), Converage.Count);
            using (IDbProvider provider = new SqlProvider())
            {
                return (int) this.BaseHelper.ExecuteScalar(provider, sqlString);
            }
        }

        public int GetCount(Type type)
        {
            string sqlString = this.Factory.CreateConverageSql(type, Converage.Count);
            using (IDbProvider provider = new SqlProvider())
            {
                return (int) this.BaseHelper.ExecuteScalar(provider, sqlString);
            }
        }

        public int GetCount(Type type, IDictionary<string, object> dic, ConditionComponent component)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateConverageSql(type, Converage.Count, "", dic, out param, component);
            using (IDbProvider provider = new SqlProvider())
            {
                return (int) this.BaseHelper.ExecuteScalar(provider, sqlString, param);
            }
        }

        public T GetEntity<T>(object pkPropertyValue) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateSingleSql(typeof(T), pkPropertyValue, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToEntity<T>(this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public T GetEntity<T>(IEntity entity, string[] propertyNames) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateSingleSql(entity, out param, propertyNames);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToEntity<T>(this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public T GetEntity<T>(string propertyName, object propertyValue) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateQueryByPropertySql(typeof(T), propertyName, propertyValue, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToEntity<T>(this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public object GetEntity(Type type, object pkPropertyValue)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateSingleSql(type, pkPropertyValue, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.baseHelper.ConvertToEntity(type, this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public object GetEntity(Type type, IEntity entity, string[] propertyNames)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateSingleSql(type, entity, out param, propertyNames);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToEntity(type, this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public object GetEntity(Type type, string propertyName, object propertyValue)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateQueryByPropertySql(type, propertyName, propertyValue, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToEntity(type, this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public IList<T> GetList<T>() where T: class
        {
            string sqlString = this.Factory.CreateQuerySql(typeof(T));
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToList<T>(this.BaseHelper.ExecuteDataReader(provider, sqlString));
            }
        }

        public IList<T> GetList<T>(IDictionary<string, object> dic) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateQueryByPropertySql(typeof(T), dic, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToList<T>(this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public IList<T> GetList<T>(IDictionary<string, object> dic, ConditionComponent component) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateQueryByPropertySql(typeof(T), dic, out param, component);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToList<T>(this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public IList<T> GetList<T>(string propertyName, object value) where T: class
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateQueryByPropertySql(typeof(T), propertyName, value, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ConvertToList<T>(this.BaseHelper.ExecuteDataReader(provider, sqlString, param));
            }
        }

        public int Update(IEntity entity)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(entity, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Update<T>(T t) where T: IEntity
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(typeof(T), t, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Update<T>(T t, string propertyName) where T: IEntity
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(typeof(T), t, out param, propertyName);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Update<T>(T t, string[] propertyNames) where T: IEntity
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(typeof(T), t, out param, propertyNames);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Update(IEntity entity, string[] propertyNames)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(entity, out param, propertyNames);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Update(IEntity entity, string propertyName)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(entity, out param, propertyName);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Update(Type type, object value)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(type, value, out param);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Update(Type type, object value, string[] propertyNames)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(type, value, out param, propertyNames);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public int Update(Type type, object value, string propertyName)
        {
            IDataParameter[] param = null;
            string sqlString = this.Factory.CreateUpdateSql(type, value, out param, propertyName);
            using (IDbProvider provider = new SqlProvider())
            {
                return this.BaseHelper.ExecuteNonQuery(provider, sqlString, param);
            }
        }

        public IBaseHelper BaseHelper
        {
            get
            {
                if (this.baseHelper == null)
                {
                    this.baseHelper = new CommonData.Data.Core.BaseHelper();
                }
                return this.baseHelper;
            }
            set
            {
                this.baseHelper = value;
            }
        }

        public IDbFactory Factory
        {
            get
            {
                if (this.factory == null)
                {
                    this.factory = new SqlFactory();
                }
                return this.factory;
            }
            set
            {
                this.factory = value;
            }
        }
    }
}

